using System;
using System.IO;
using Oracle.ManagedDataAccess.Client;
using OracleInternal.Common;

namespace OracleInternal.NotificationServices
{
	internal class OutputBuffer
	{
		private const int BUFFERSIZE = 1024;

		private Stream ostr;

		private sbyte[] buffer;

		private int spaceleft;

		private int position;

		protected internal OutputBuffer(Stream o)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.OutputBuffer, OracleTraceFuncName.ctor);
			}
			ostr = o;
			buffer = new sbyte[1024];
			spaceleft = 1024;
			position = 0;
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.OutputBuffer, OracleTraceFuncName.ctor);
			}
		}

		protected internal virtual void putBytes(sbyte[] b, int len)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.OutputBuffer, OracleTraceFuncName.putBytes);
			}
			try
			{
				if (spaceleft >= len)
				{
					Array.Copy(b, 0, buffer, position, len);
					spaceleft -= len;
					position += len;
				}
				else if (len > 1024)
				{
					if (position > 0)
					{
						ostr.Write(SupportClass.ToByteArray(buffer), 0, position);
					}
					position = 0;
					spaceleft = 1024;
					ostr.Write(SupportClass.ToByteArray(b), 0, len);
				}
				else
				{
					Array.Copy(b, 0, buffer, position, spaceleft);
					ostr.Write(SupportClass.ToByteArray(buffer), 0, 1024);
					Array.Copy(b, spaceleft, buffer, 0, len - spaceleft);
					position = len - spaceleft;
					spaceleft = 1024 - position;
				}
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.OutputBuffer, OracleTraceFuncName.putBytes, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.OutputBuffer, OracleTraceFuncName.putBytes);
				}
			}
		}

		protected internal virtual void putString(string s)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.OutputBuffer, OracleTraceFuncName.putString);
			}
			try
			{
				putBytes(SupportClass.ToSByteArray(SupportClass.ToByteArray(s)), s.Length);
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.OutputBuffer, OracleTraceFuncName.putString, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.OutputBuffer, OracleTraceFuncName.putString);
				}
			}
		}

		protected internal virtual void putByte(sbyte b)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.OutputBuffer, OracleTraceFuncName.putByte);
			}
			try
			{
				if (spaceleft == 0)
				{
					ostr.Write(SupportClass.ToByteArray(buffer), 0, 1024);
					spaceleft = 1024;
					position = 0;
				}
				buffer[position] = b;
				position++;
				spaceleft--;
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.OutputBuffer, OracleTraceFuncName.putByte, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.OutputBuffer, OracleTraceFuncName.putByte);
				}
			}
		}

		protected internal virtual void flush()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.OutputBuffer, OracleTraceFuncName.flush);
			}
			try
			{
				if (position > 0)
				{
					ostr.Write(SupportClass.ToByteArray(buffer), 0, position);
				}
				ostr.Flush();
				position = 0;
				spaceleft = 1024;
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.OutputBuffer, OracleTraceFuncName.flush, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.OutputBuffer, OracleTraceFuncName.flush);
				}
			}
		}
	}
}
